/* James McTaggart (jcm28) Informatics
Multimedia Communications Technology - 17th May 2007
In making this submission I declare that my work contains no examples
of misconduct, such as plagiarism, collusion, or fabrication of results.
*/

package client;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.PriorityQueue;
import java.util.Timer;


public class Client{

	private PriorityQueue<Sample> samples;
	private int delay;
	private int period;
	private byte[] outData = new byte[60];
	private byte[] inData = new byte[60];
	private InetAddress serverIP;
	private InetAddress radioIP;
	private int serverPort;
	private int radioPort;
	private static final int retries = 5;
	private boolean bleep;
	
	
	public Client(String host, int port) {
		// TODO Auto-generated constructor stub
		samples = new PriorityQueue<Sample>();

		try {
			serverIP = InetAddress.getByName(host);
			serverPort = port;
			DatagramSocket clientSocket = new DatagramSocket();
			
			//Send connect message to server
			clientSocket.send(ClientProtocol.get101(serverIP,serverPort));
			
			DatagramPacket inPacket = new DatagramPacket(inData,inData.length);
			clientSocket.receive(inPacket);
			String in = new String(inPacket.getData());
			int n = getMessageID(in);
			//Allow a maximum of 5 retries if correct response not received
			for(int i = 0; i < retries&&n!=201; i++){
				clientSocket.send(ClientProtocol.get101(serverIP,serverPort));
				clientSocket.receive(inPacket);
				in = new String(inPacket.getData());
				n = getMessageID(in);
			}
			
			if(n!=201){
				System.out.println("Unable to connect to server after 5 retries please restart application to retry.");
				System.exit(0);
			}
			
			parse201(in);
			
			System.out.println("Now connected to server. Please enter 'START' to start transmission");
			
			BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
			String user = userIn.readLine();
			while(!user.equals("START")){
				System.out.println("Now connected to server. Please enter 'START' to start transmission");
				user = userIn.readLine();	
			}
			
			RadioReceiver receiver = new RadioReceiver(this,radioIP,radioPort);
			receiver.start();
			Thread.yield();
			DisplayThread dt = new DisplayThread(this);
			Timer timer = new Timer();
			timer.scheduleAtFixedRate(dt, delay, period);
			
			ClientBleepThread bleepThread = new ClientBleepThread(this,clientSocket,delay);
			bleepThread.start();
			
			
			user = userIn.readLine();
			while(!user.equals("STOP")){
				Thread.yield();
				user = userIn.readLine();
			}
			clientSocket.send(ClientProtocol.get102(serverIP,serverPort));
			receiver = null;
			timer.cancel();
			System.out.println("Radio Receiver now closed");
			System.exit(0);
		} catch (Exception e) {
			// TODO: handle exception
		}

	}
	
	public synchronized boolean isBleep() {
		return bleep;
	}

	public synchronized void setBleep(boolean bleep) {
		this.bleep = bleep;
	}

	private void parse201(String message)throws UnknownHostException{
		//13-19 = delay, 19-25 = period, 25-29 = radioPort
		//29 onwards = #radioAddress#
		delay = Integer.parseInt(message.substring(13, 19));
		period = Integer.parseInt(message.substring(19,25));
		radioPort = Integer.parseInt(message.substring(25, 29));
		int a = message.substring(30).indexOf("#");
		radioIP = InetAddress.getByName(message.substring(30).substring(0, a));
		System.out.println();
	}
	
	private int getMessageID(String message) {
		try {
			int id = Integer.parseInt(message.substring(0, 3));
			if (id != 201 && id != 202) {
				return -1;
			}
			return id;
		} catch (NumberFormatException e) {
			return -1;
		}
	}

	public void print(Sample sample){
		System.out.println(sample);
	}
	public void print(String s){
		System.out.println(s);
	}
	public synchronized void addSample(Sample sample){
		//if(!samples.contains(sample))samples.add(sample);
		samples.add(sample);
	}
	
	public synchronized Sample removeSample(){
		return samples.poll();
	}

	public synchronized void bleepSample(int sampleNo){
		Sample s = new Sample(sampleNo, "BLEEP!");
		samples.remove(s);
		samples.add(s);
	}
	
	public synchronized Sample peekSample(){
		return samples.peek();
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		if(args.length==0){
			Client client  = new Client("localhost", 7777);
		}
		else{
			int port = Integer.parseInt(args[1]);
			Client client = new Client(args[0],port);
		}
	}

}
